import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { SysConfigEntity } from './entities/config.entity';
import { In, Repository } from 'typeorm';
import { RedisService } from '../../redis/redis.service';
import { CreateConfigDto, ListConfigDto, UpdateConfigDto } from './dto';
import { ResultData } from 'src/common/utils/result';
import { CacheEnum } from 'src/common/enum';
import { ExportTable } from 'src/common/utils/export';
import { Response } from 'express';

@Injectable()
export class ConfigService {
  constructor(
    @InjectRepository(SysConfigEntity)
    private readonly sysConfigEntityRep: Repository<SysConfigEntity>,
    private readonly redisService: RedisService,
  ) {}

  /**
   * 创建
   * @param createConfigDto
   * @returns
   */
  async create(createConfigDto: CreateConfigDto) {
    await this.sysConfigEntityRep.save(createConfigDto);
    return ResultData.ok();
  }

  /**
   * 查询
   * @param query
   */
  async findAll(query: ListConfigDto) {
    const entity = this.sysConfigEntityRep.createQueryBuilder('entity');

    entity.where('entity.delFlag = :delFlag', { delFlag: '0' });

    if (query.configName) {
      entity.andWhere(`entity.configName LIKE  "%${query.configName}%"`);
    }

    if (query.configKey) {
      entity.andWhere(`entity.configKey LIKE  "%${query.configKey}%"`);
    }

    if (query.configType) {
      entity.andWhere(`entity.configType = :configType`, { configType: query.configType });
    }

    if (query.params?.beginTime && query.params?.endTime) {
      entity.where(`entity.createTime BETWEEN :start AND :end`, { start: query.params.beginTime, end: query.params.endTime });
    }

    if (query.pageSize && query.pageNum) {
      entity.skip(query.pageSize * (query.pageNum - 1)).take(query.pageSize);
    }
    const [list, total] = await entity.getManyAndCount();
    return ResultData.ok({ list, total });
  }

  /**
   * 查看某个配置
   * @param configId
   * @returns
   */
  async findOne(configId: number) {
    const data = await this.sysConfigEntityRep.findOne({
      where: { configId },
    });
    return ResultData.ok(data);
  }

  /**
   * 根据key查找某个对应信息
   * @param configKey
   * @returns
   */
  async findOneByConfigKey(configKey: string) {
    const data = await this.getConfigValue(configKey);
    return ResultData.ok(data);
  }

  /**
   * 根据配置键值异步查找一条配置信息。
   * @param configKey 配置的键值，用于查询配置信息。
   * @returns 返回一个结果对象，包含查询到的配置信息。如果未查询到，则返回空结果。
   */
  async getConfigValue(configKey: string) {
    // 尝试从Redis缓存中获取配置信息
    const cacheData = await this.redisService.get(`${CacheEnum.SYS_CONFIG_KEY}${configKey}`);
    if (cacheData) {
      // 如果缓存中存在配置信息,则直接返回
      return cacheData;
    }

    // 没找到，则从数据库中查询
    const data = await this.sysConfigEntityRep.findOne({ where: { configKey } });
    // 将从数据库中查询到的内容存储到Redis里面
    await this.redisService.set(`${CacheEnum.SYS_CONFIG_KEY}${configKey}`, data.configValue);
    // 返回数据
    return data.configValue;
  }

  /**
   * 更新
   * @param updateConfigDto
   * @returns
   */
  async update(updateConfigDto: UpdateConfigDto) {
    await this.sysConfigEntityRep.update({ configId: updateConfigDto.configId }, updateConfigDto);
    return ResultData.ok();
  }

  /**
   * 删除
   * @param configIds
   * @returns
   */
  async remove(configIds: number[]) {
    const list = await this.sysConfigEntityRep.find({
      where: { configId: In(configIds), delFlag: '0' },
      select: ['configType', 'configKey'],
    });
    const item = list.find((item) => item.configType === 'Y');
    if (item) {
      return ResultData.fail(500, `内置参数【${item.configKey}】不能删除`);
    }
    const data = await this.sysConfigEntityRep.update({ configId: In(configIds) }, { delFlag: '1' });
    return ResultData.ok(data);
  }

  /**
   * 刷新缓存
   * @returns
   */
  async refreshCache() {
    const list = await this.sysConfigEntityRep.find({ where: { delFlag: '0' } });
    list.forEach((item) => {
      this.redisService.set(`${CacheEnum.SYS_CONFIG_KEY}${item.configKey}`, item.configValue);
    });
    return ResultData.ok();
  }

  async export(res: Response, body: ListConfigDto) {
    delete body.pageNum;
    delete body.pageSize;
    const list = await this.findAll(body);
    const options = {
      sheetName: '参数管理',
      data: list.data.list,
      header: [
        { title: '参数主键', dataIndex: 'configId' },
        { title: '参数名称', dataIndex: 'configName' },
        { title: '参数键名', dataIndex: 'configKey' },
        { title: '参数键值', dataIndex: 'configValue' },
        { title: '系统内置', dataIndex: 'configType' },
      ],
      dictMap: {
        configType: { Y: '是', N: '否' },
      },
    };
    ExportTable(options, res);
  }
}
